package com.example.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.example.dto.UserDto;
import com.example.entity.*;
import com.example.mapper.UserAMapper;
import com.example.mapper.UserMapper;
import com.example.mapper.UserRoleMapper;
import com.example.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author hotta
 * @since 2023-05-31
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private UserAService userAService;

    @Autowired
    private PositionService positionService;

    @Autowired
    private DepartmentService departmentService;

    @Autowired
    private RoleMenuService roleMenuService;

    @Autowired
    private MenuService menuService;


    @Override
    public Map<String, Object> login(User user) {
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(User::getUsername, user.getUsername());
        User one = this.getOne(userLambdaQueryWrapper);
        //结果不为空，则生存token，并且将用户信息存入jwt
        if (one != null && passwordEncoder.matches(user.getPassword(), one.getPassword())) {
            //密码加密
            String key = "user" + UUID.randomUUID();
            //存入redis
            one.setPassword(null);
            redisTemplate.opsForValue().set(key, one, 30, TimeUnit.MINUTES);
            //返回数据
            HashMap<String, Object> map = new HashMap<>();
            map.put("token", key);
            return map;
        }
        return null;
    }
//    @Override
//    public Map<String, Object> login(User user) {
//        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
//        userLambdaQueryWrapper.eq(User::getUsername, user.getUsername());
//        User one1 = this.getOne(userLambdaQueryWrapper);
//        userLambdaQueryWrapper.eq(User::getPassword, user.getPassword());
//        User one = this.getOne(userLambdaQueryWrapper);
//
//        log.info("user1111111111111111111111111111 = " + one1);
//        log.info("user222222222222222222222222222 = " + one);
//        //结果不为空，则生存token，并且将用户信息存入jwt
//        if (one != null) {
//            //密码加密
//            String key = "user" + UUID.randomUUID();
//
//            //存入redis
//            one.setPassword(null);
//            redisTemplate.opsForValue().set(key, one, 30, TimeUnit.MINUTES);
//
//            //返回数据
//            HashMap<String, Object> map = new HashMap<>();
//            map.put("token", key);
//            return map;
//        }
//        return null;
//    }

    @Override
    @Transactional
    public Map<String, Object> getUserInfo(String token) {
        Object o = redisTemplate.opsForValue().get(token);
        if (o != null) {
            //反序列化
            User user = JSON.parseObject(JSON.toJSONString(o), User.class);
            HashMap<String, Object> map = new HashMap<>();
            map.put("name", user.getUsername());
            map.put("avatar", user.getAvatar());


            log.info("----------------------");
            log.info("{}", user);

            LambdaQueryWrapper<UserRole> userRoleLambdaQueryWrapper = new LambdaQueryWrapper<>();
            userRoleLambdaQueryWrapper.eq(UserRole::getUserId, user.getId());
            List<UserRole> list = userRoleService.list(userRoleLambdaQueryWrapper);

            List<String> collect = list.stream().map((item -> {
                LambdaQueryWrapper<Role> roleLambdaQueryWrapper = new LambdaQueryWrapper<>();
                roleLambdaQueryWrapper.eq(Role::getId, item.getRoleId());
                String roleName = roleService.getOne(roleLambdaQueryWrapper).getRoleName();
                return roleName;
            })).collect(Collectors.toList());

            //权限列表
            LambdaQueryWrapper<UserRole> userRoleLambdaQueryWrapper1 = new LambdaQueryWrapper<>();
            userRoleLambdaQueryWrapper1.eq(UserRole::getUserId, user.getId());
            UserRole userRole = userRoleService.getOne(userRoleLambdaQueryWrapper1);

            log.info("userRole{}", userRole);

            LambdaQueryWrapper<RoleMenu> roleMenuLambdaQueryWrapper = new LambdaQueryWrapper<>();
            roleMenuLambdaQueryWrapper.select(RoleMenu::getMenuId);
            roleMenuLambdaQueryWrapper.eq(RoleMenu::getRoleId, userRole.getRoleId());
            List<RoleMenu> list1 = roleMenuService.list(roleMenuLambdaQueryWrapper);

            log.info("RoleMenu{}", list1);

            List<Long> menuIdList = list1.stream().map(item -> {
                Long ids = item.getMenuId();
                return ids;
            }).collect(Collectors.toList());

            log.info("{}", menuIdList);

            LambdaQueryWrapper<Menu> menuLambdaQueryWrapper = new LambdaQueryWrapper<>();
            menuLambdaQueryWrapper.in(Menu::getId, menuIdList);
            menuLambdaQueryWrapper.eq(Menu::getParentId, 0);
            List<Menu> menuList = menuService.list(menuLambdaQueryWrapper);

            log.info("{}", menuList);

            List<Menu> menuList1 = menuList.stream().map(item -> {
                Map<String, Object> map1 = new HashMap<>();
                map1.put("icon", item.getIcon());
                map1.put("title", item.getTitle());

                item.setMeta(map1);
                return item;
            }).collect(Collectors.toList());

            if (menuList1 != null) {
                for (Menu menu : menuList1) {
                    LambdaQueryWrapper<Menu> wrapper3 = new LambdaQueryWrapper<>();
                    wrapper3.in(Menu::getId, menuIdList);
                    wrapper3.eq(Menu::getParentId, menu.getId());
                    List<Menu> menus = menuService.list(wrapper3);

                    List<Menu> collect1 = menus.stream().map(item -> {
                        Map<String, Object> map2 = new HashMap<>();
                        map2.put("icon", item.getIcon());
                        map2.put("title", item.getTitle());

                        item.setMeta(map2);
                        return item;
                    }).collect(Collectors.toList());
                    menu.setChildren(collect1);
                }
            }

            map.put("menuList", menuList);
            map.put("roles", collect);
            log.info("{}",menuList);
            log.info("{}--------------", map);
            return map;
        }
        return null;
    }

    @Override
    public void logout(String token) {
        redisTemplate.delete(token);
    }

    @Override
    @Transactional
    public void addUser(UserDto userDto) {
        //写入用户表，写入用户角色表
        this.save(userDto);
        Long roleId = userDto.getRoleId1();
        userRoleMapper.insert(new UserRole(null, userDto.getId(), roleId));

        UserA userA = new UserA();
        BeanUtils.copyProperties(userDto, userA);

        long id = IdWorker.getId();
        userA.setId(id);
        log.info("{}", userA);
        userA.setUserId(userDto.getId());
        userAService.save(userA);
    }

    @Override
    public UserDto getUserById(Long id) {
        User user = this.getById(id);

        LambdaQueryWrapper<UserRole> userRoleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userRoleLambdaQueryWrapper.eq(UserRole::getUserId, id);

        user.setRoleId1(userRoleService.getOne(userRoleLambdaQueryWrapper).getRoleId());

        UserDto userDto = new UserDto();
        BeanUtils.copyProperties(user, userDto);

        LambdaQueryWrapper<UserA> userALambdaQueryWrapper = new LambdaQueryWrapper<>();
        userALambdaQueryWrapper.eq(UserA::getUserId, id);
        UserA one = userAService.getOne(userALambdaQueryWrapper);


        LambdaQueryWrapper<Department> departmentLambdaQueryWrapper = new LambdaQueryWrapper<>();
        departmentLambdaQueryWrapper.eq(Department::getId, one.getDepartmentId());
        LambdaQueryWrapper<Position> positionLambdaQueryWrapper = new LambdaQueryWrapper<>();
        positionLambdaQueryWrapper.eq(Position::getId, one.getPositionId());


        userDto.setDepartmentId(one.getDepartmentId());
        userDto.setDepartmentName(departmentService.getOne(departmentLambdaQueryWrapper).getName());
        userDto.setPositionId(one.getPositionId());
        userDto.setPositionName(positionService.getOne(positionLambdaQueryWrapper).getName());

        return userDto;
    }

    @Override
    @Transactional
    public void updateUser(UserDto userDto) {
        //更新用户，删除用户角色，新增用户角色
        this.updateById(userDto);
        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRole::getUserId, userDto.getId());
        userRoleService.remove(wrapper);

        userRoleMapper.insert(new UserRole(null, userDto.getId(), userDto.getRoleId1()));

        LambdaQueryWrapper<UserA> userALambdaQueryWrapper = new LambdaQueryWrapper<>();
        userALambdaQueryWrapper.eq(UserA::getUserId, userDto.getId());
        UserA one = userAService.getOne(userALambdaQueryWrapper);

        one.setDepartmentId(userDto.getDepartmentId());
        one.setPositionId(userDto.getPositionId());

        userAService.updateById(one);


    }

    @Override
    public void deleteUserById(Long id) {
        this.removeById(id);
        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRole::getUserId, id);
        userRoleService.remove(wrapper);

        LambdaQueryWrapper<UserA> userALambdaQueryWrapper = new LambdaQueryWrapper<>();
        userALambdaQueryWrapper.eq(UserA::getUserId, id);

        userAService.removeById(userAService.getOne(userALambdaQueryWrapper).getId());
    }
}
